package com.tanhua.server.service;

import cn.hutool.core.date.DateTime;
import com.tanhua.commons.constant.Constants;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.dubbo.api.db.OptionApi;
import com.tanhua.dubbo.api.db.ProblemApi;
import com.tanhua.dubbo.api.db.QuestionnaireApi;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.DimensionApi;
import com.tanhua.model.db.Option;
import com.tanhua.model.db.Problem;
import com.tanhua.model.db.Questionnaire;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.enums.Conclusion;
import com.tanhua.model.constants.DimensionType;
import com.tanhua.model.enums.DimensionValue;
import com.tanhua.model.enums.ReportCover;
import com.tanhua.model.mongo.Dimension;
import com.tanhua.model.vo.QuestionnaireVo;
import com.tanhua.model.vo.ViewreportVo;
import com.tanhua.server.interceptor.MapValueComparator;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.lang3.RandomUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @description: 测试灵魂
 * @author: zhangzheng
 * @date: 2021/12/25 17:12
 */
@Service
public class TestSoulService {

    @DubboReference
    private DimensionApi dimensionApi;

    @DubboReference
    private ProblemApi problemApi;

    @DubboReference
    private OptionApi optionApi;

    @DubboReference
    private QuestionnaireApi questionnaireApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    /**
     * 提交问卷  zhengzheng、liuhaijie、zhangfude
     *
     * @param param1 answers
     * @return 报告Id
     */
    public String submitQuestionnaire(Map<String,List<Map<String,String>>> param1) {
        List<Map<String,String>> param = param1.get("answers");
        if (param == null || param.size() != 10) {
            throw new TanHuaException("试题选项不能为空或未选择十条选项");
        }

        Problem problem = null;

        Map<String, Integer> dimenValueMap = new HashMap<>();
        dimenValueMap.put(DimensionType.ABSTRACT, 0);
        dimenValueMap.put(DimensionType.JUDGE, 0);
        dimenValueMap.put(DimensionType.LOGICAL, 0);
        dimenValueMap.put(DimensionType.OUTGOING, 0);

        for (Map<String,String> map : param) {

            String questionId = map.get("questionId");
            if (StringUtils.isEmpty(questionId)) {
                throw new TanHuaException("试题编号不能未空");
            }
            problem = problemApi.getQuestion(questionId);
            if (problem == null) {
                throw new TanHuaException("问题不存在");
            }
            String dimensionType = problem.getDimension();
            if (StringUtils.isEmpty(dimensionType)) {
                throw new TanHuaException("维度不能为空");
            }

            String optionId = map.get("optionId");
            if (StringUtils.isEmpty(optionId)) {
                throw new TanHuaException("选项编号不能未空");
            }
            Option option = optionApi.getOption(optionId);
            if (option == null) {
                throw new TanHuaException("选项不存在");
            }

            countDimension(dimenValueMap, option, dimensionType);
        }

        Map<String, Integer> sortedMap = sortVdo(dimenValueMap);

        Long userId = UserHolder.getUserId();

        Dimension dimension = new Dimension();
        dimension.setUserId(userId);

        Set<String> set = sortedMap.keySet();
        int index = 0;

        for (String s : set) {
            if (index == 0) {
                setVdo(s, DimensionValue.LOW.getDimensionValue(), dimension);
            } else if (index == 1) {
                setVdo(s, DimensionValue.MEDIUM.getDimensionValue(), dimension);
            } else if (index == 2) {
                setVdo(s, DimensionValue.HIGH.getDimensionValue(), dimension);
            } else {
                setVdo(s, DimensionValue.GREAT.getDimensionValue(), dimension);
            }
            index++;
        }
        Long questionnaireId = problem.getQuestionnaireId();
        if (questionnaireId == null) {
            throw new TanHuaException("问卷Id不能为Null");
        }
        dimension.setQuestionnaireId(questionnaireId);
        dimension.setCreateDate(DateTime.now().getTime());

        String dimenId = dimensionApi.saveQuestionnaire(dimension);
        if (StringUtils.isEmpty(dimenId)) {
            throw new TanHuaException("提交生成报告失败");
        }
        return dimenId;
    }

    /**
     * 对维度大小进行排序 zhangzheng、liuhaijie、zhangfude
     *
     * @param dimenValueMap 维度Map
     * @return 排序后维度Map
     */
    private Map<String, Integer> sortVdo(Map<String, Integer> dimenValueMap) {
        Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();

        List<Map.Entry<String, Integer>> entryList = new ArrayList<Map.Entry<String, Integer>>(
                dimenValueMap.entrySet());
        Collections.sort(entryList, new MapValueComparator());

        Iterator<Map.Entry<String, Integer>> iter = entryList.iterator();
        Map.Entry<String, Integer> tmpEntry = null;
        while (iter.hasNext()) {
            tmpEntry = iter.next();
            sortedMap.put(tmpEntry.getKey(), tmpEntry.getValue());
        }
        return sortedMap;
    }

    /**
     * 设置四个维度  zhangzheng、liuhaijie、zhangfude
     *
     * @param dimensionType  维度类型
     * @param dimensionValue 维度值
     * @param dimension      报告
     */
    private void setVdo(String dimensionType, Integer dimensionValue, Dimension dimension) {
        switch (dimensionType) {
            case DimensionType.JUDGE:
                dimension.setJudge(dimensionValue);
                break;
            case DimensionType.LOGICAL:
                dimension.setLogical(dimensionValue);
                break;
            case DimensionType.ABSTRACT:
                dimension.set_abstract(dimensionValue);
                break;
            case DimensionType.OUTGOING:
                dimension.setOutgoing(dimensionValue);
                break;
            default:
                throw new TanHuaException("维度不存在！！！");
        }
    }

    /**
     * 计算维度值 zhangzheng、liuhaijie、zhangfude
     *
     * @param dimenValueMap 维度集合
     * @param option        选项
     * @param dimen         维度类型
     */
    private void countDimension(Map<String, Integer> dimenValueMap, Option option, String dimen) {
        Integer abs = dimenValueMap.get(dimen);
        abs += option.getScore();
        dimenValueMap.put(dimen, abs);
    }

    /**
     * 查看测试灵魂查询结果
     * @author:HeShuai,PanXinFu,LiZhen
     * @param id :报告id
     * @return
     */
    public ViewreportVo viewResults(String id) {
        Long userId = UserHolder.getUserId();
        ViewreportVo vo=new ViewreportVo();
        //根据登录id查询登录用户的性别
        UserInfo loginUserInfo = userInfoApi.getUserInfo(userId);
        //根据报告id查询报告表
        Dimension dimension =dimensionApi.findById(id);
        //从报告表中查询到4个维度对应的值
        Integer outgoingScore = dimension.getOutgoing();//外向的分数
        Integer judgeScore = dimension.getJudge();//判断的分数
        Integer abstractScore= dimension.get_abstract();//抽象的分数
        Integer logicalScore = dimension.getLogical();//理性的分数
        //根据枚举查询对应的分数,定义map接收转换为list存入vo中
        List<Map<String, String>> dimensionsList = new ArrayList<>();
        Map<String, String> outgoingMap = new HashMap<>();
        Map<String, String> judgeMap = new HashMap<>();
        Map<String, String> abstractMap = new HashMap<>();
        Map<String, String> logicalMap = new HashMap<>();
        outgoingMap.put("key", DimensionType.OUTGOING);
        judgeMap.put("key", DimensionType.JUDGE);
        abstractMap.put("key", DimensionType.ABSTRACT);
        logicalMap.put("key", DimensionType.LOGICAL);
        outgoingMap.put("value", outgoingScore.toString() + "%");
        judgeMap.put("value", judgeScore.toString() + "%");
        abstractMap.put("value", abstractScore.toString() + "%");
        logicalMap.put("value", logicalScore.toString() + "%");
        dimensionsList.add(outgoingMap);
        dimensionsList.add(judgeMap);
        dimensionsList.add(abstractMap);
        dimensionsList.add(logicalMap);
        vo.setDimensions(dimensionsList);//存入维度值
        //根据分数排序推荐对应的照片
        Map<String, String> map = dimensionComparator(outgoingScore,judgeScore,abstractScore,logicalScore);
        vo.setConclusion(map.get("conclusion"));
        vo.setCover(map.get("cover"));
        dimensionApi.updateCover(map.get("cover"),id);//保存头像
        //根据维度查询相关用户的动态
        List<Dimension> dimensionList =dimensionApi.findByScore(dimension.getCover(), userId);
        //3:定义一个list集合收集id
        List<Long> userIds = new ArrayList<>();
        //4:遍历根据分数查询相关推荐的10个人
        if (!CollectionUtils.isEmpty(dimensionList)) {
            for (Dimension dimension1 : dimensionList) {
                userIds.add(dimension1.getUserId());
            }
        }else{
            userIds = getDefaultSimilar(userId);
        }
        //：根据报告获取到userId查询userInfo表
        String targetGender;
        if (loginUserInfo.getGender().equals("man")) {
            targetGender = "woman";
        }else{
            targetGender = "man";
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setGender(targetGender);
        Map<Long, UserInfo> reMaps = userInfoApi.findByIds(userIds, userInfo);
        //定义一个List集合用于similarYou
        List<Map<String, Object>> similarYouList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(reMaps)) {
            Set<Long> keySet = reMaps.keySet();
            for (Long key : keySet) {
                Map<String, Object> similarYouMap = new HashMap<>();
                similarYouMap.put("id", key.intValue());
                similarYouMap.put("avatar",reMaps.get(key).getAvatar());
                similarYouList.add(similarYouMap);
            }
        }
        //4：封装vo返回
        vo.setSimilarYou(similarYouList);//封装与你相似
        return vo;
    }

    /**
     * 比较4个维度的最大值
     * @author:HeShuai,PanXinFu,LiZhen
     * @param outgoingScore
     * @param judgeScore
     * @param abstractScore
     * @param logicalScore
     * @return 返回对应的枚举照片以及对应的结果
     */
    public Map<String,String> dimensionComparator(Integer outgoingScore,Integer judgeScore,Integer abstractScore,Integer logicalScore){
        List<Integer> list = new ArrayList<>();
        list.add(outgoingScore);
        list.add(judgeScore);
        list.add(abstractScore);
        list.add(logicalScore);
        Optional<Integer> max = list.stream().max(Comparator.comparingInt(Integer::intValue));
        Integer maxValue = max.get();
        Map<String,String> map=new HashMap<>();
        if (maxValue==outgoingScore){
            map.put("conclusion", Conclusion.OWL.getConclusion());
            map.put("cover",ReportCover.OWL.getReportCover());
            return map;
        }else if (maxValue==judgeScore){
            map.put("conclusion", Conclusion.RABBIT.getConclusion());
            map.put("cover",ReportCover.RABBIT.getReportCover());
            return map;
        }else if (maxValue==abstractScore){
            map.put("conclusion", Conclusion.FOX.getConclusion());
            map.put("cover",ReportCover.FOX.getReportCover());
            return map;
        }else if (maxValue==logicalScore){
            map.put("conclusion", Conclusion.LION.getConclusion());
            map.put("cover",ReportCover.LION.getReportCover());
            return map;
        }
        return map;
    }

    /**
     * 问卷列表
     * @return 问卷列表详细信息
     */
    public List<QuestionnaireVo> questionnaireList() {
        Long userId = UserHolder.getUserId();
        List<Questionnaire> questionnaireList = questionnaireApi.findAll();
        Map<Long, Dimension> history = dimensionApi.findUserHistory(userId);
        List<QuestionnaireVo> list = new ArrayList<>();
        for (Questionnaire questionnaire : questionnaireList) {
            QuestionnaireVo q = QuestionnaireVo.init(questionnaire);
            Dimension dimension1 = history.get(questionnaire.getId());
            Dimension dimension2 = history.get(questionnaire.getId() - 1);
            if(dimension1 != null){
                q.setReportId(dimension1.getId().toString());
            }
            if(dimension2 == null && questionnaire.getId() > 1){
                q.setIsLock(1);
            }
            list.add(q);
        }
        return list;
    }

    private List<Long> getDefaultSimilar(Long userId){
        List<Long> userIds = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            long similarId = userId % 99 + RandomUtils.nextInt(1,1000);
            userIds.add(similarId);
        }
        return userIds;
    }
}
